<?php
/**
 * Class for loading appropriate context for Adroit MVC framework
 *
 * @package adroit
 */
class Adroit{
    
	public static $package = '';
	
    public static $controller = '';
    
    public static $action = '';
	
	public static $nonActionView = '';
    
    /**
     * Logger
     *
     * @var AdroitLogger
     */
    public static $logger;

    /**
     * @var Array Configuration parameters
     */
    public static $config = Array();

    /**
     * @var AdroitAlertHandler
     */
    public static $alerts;

    /**
     * @var Array Parameters from HTTP Request (GET/POST)
     */
    private static $requestData = Array();

    /**
     * Called from specific page implementation before calling loadPage().
     *
     * @param String $page Page specific configuration name
     */
    public static function initialize() {
        if(self::$config['debugging']) {
            self::enableDebugging();
        }
        self::configureDB();
        session_start();
        require_once('util/AdroitAlertHandler.class.php');
        if(isset($_SESSION[AdroitAlertHandler::$SESSION_KEY])) {
            self::$alerts = $_SESSION[AdroitAlertHandler::$SESSION_KEY];
            session_unregister(AdroitAlertHandler::$SESSION_KEY);
        }else {
            self::$alerts = new AdroitAlertHandler();
        }
    }
    
    public static function parseRequest($request=null) {
    	$controllerPath = APP_PATH . 'controller/';
    	
    	$request = $request === null ? @$_SERVER['REDIRECT_URL'] == '' ? @$_SERVER['RESPONSE_URI'] : $_SERVER['REDIRECT_URL'] : $request;
    	$route = explode('/', substr($request, strlen(WEB_ROOT)));    	

    	//1: Nothing in 0 = Index
    	if($route[0] == '') {
    		Adroit::$controller = 'Index';
    		Adroit::$action = 'Index';
    	}else {
    		//Determine package route
    		while(@$route[0] != '' && is_dir($controllerPath . strtolower(Adroit::$package) . (Adroit::$package != '' ? '/' : '') . $route[0])) {
    			Adroit::$package .= Adroit::$package !== '' ? '/' : '';
    			Adroit::$package .= $route[0];
    			array_shift($route);
    		}
    		//Determine Controller
    		if(@$route[0] != '' && file_exists($controllerPath . (Adroit::$package != '' ? Adroit::$package . '/' : '') . ucwords($route[0]) . '.controller.php')) {
    			Adroit::$controller = ucwords($route[0]);
    			array_shift($route);
    		}else {
    			Adroit::$controller = 'Index';
    		}
    		//Determine Action
			$className = Adroit::$controller . 'Controller';

			try {
    			$method = new ReflectionMethod(Adroit::$controller . 'Controller', @$route[0] . 'Action');
    		}catch(ReflectionException $exception) {
    			$method = null;
    		}

    		if($method != null) {
    			Adroit::$action = ucwords($route[0]);
    			array_shift($route);
    		}else {
    			Adroit::$action = 'Index';
				if(file_exists(APP_PATH . 'view/' . BaseView::getTemplatePath() . @$route[0] . '.tpl')) {
					Adroit::$nonActionView = $route[0];
					array_shift($route);
				}
    		}
    		//Append additional arguments

    		if(count($route) > 0) {
	    		foreach($route AS $key => $value) {
					self::addRequestParam('arg' . $key, $value);
				}	
    		}
    	}
    }
    
    /**
     * Called from adroit-config.php to load GET/POST request parameters.
     *
     * @param Array $get
     * @param Array $post
     */
    public static function loadRequestData($get, $post) {
        self::$requestData = array_merge($get, $post);
    }
    
	public static function addRequestParam($key, $value) {
		if($value != '') {
	    	self::$requestData[$key] = $value;
		}
    }

    /**
     * Called from specific page implementation after calling initialize().
     * Fires off the appropriate controller.
     *
     * @param boolean $restricted
     */
    public static function loadPage() {
        $controller = self::getController();
        $controller->process(self::$requestData, self::$action);
        if($controller->view != null) {
            $layout = self::getLayout($controller);
            $controller->view->render($controller->data, 'layouts/' . $layout);
        }
    }


    /**
     * Loads the appropriate controller along with its model and view.
     *
     * @param boolean $restricted
     * @return IController
     */
    private static function getController() {
    	$className = 'Base';
        if(file_exists(APP_PATH . 'controller' . '/' . (Adroit::$package != '' ? Adroit::$package . '/' : '') . self::$controller . '.controller.php')) {
            $className = self::$controller;
        }
        $class = $className . 'Controller';
        $controller = new $class();
        $controller->view = self::generateView();
        return $controller;
    }

    /**
     * Wrapper function for loading the appropriate view.
     * Sets the Smarty object on the view, and configures the Smarty template and config file.
     *
     * @return BaseView
     */
    private static function generateView() {
        $className = 'Base';
        if(file_exists(APP_PATH . 'view' . '/' . self::$controller . self::$action . '.view.php')) {
            $className = self::$controller . self::$action;
        }else if(file_exists(APP_PATH . 'view' . '/' . self::$controller . '.view.php')) {
            $className = self::$controller;
        }
        $class = $className . 'View';
        return new $class();
    }

    /**
     * Initializes AdroitDB object for db access.
     * Also sets up Session to save to DB isntead of file system according to configuration
     */
    private static function configureDB() {
        require_once('db/AdroitDB.class.php');
        if(@isset(self::$config['db']['name']) && self::$config['db']['name'] != '') {
            AdroitDB::connect(self::$config['db']);
            if(self::$config['sessionDB'] == true) {
            	require_once('util/AdroitDBSession.class.php');
                new AdroitDBSession();
            }
        }
    }

    /**
     * Enables basic php warning messages for debugging
     */
    private static function enableDebugging() {
        require_once('util/AdroitLogger.class.php');
        self::$logger = new AdroitLogger();
        ini_set("display_errors", "1");
        ini_set("track_errors", "1");
        error_reporting(E_ALL);
    }
    
    private static function getLayout($controller) {
        $layoutPath = APP_PATH . 'view/layouts/';
        $layout = 'base';
        if(Adroit::$package != '') {
        	$pkgPath = $layoutPath . Adroit::$package . '/';
	        if($controller->layout != null && file_exists($pkgPath . $controller->layout . '.tpl')) {
	            $layout = strtolower(Adroit::$package) . '/' . $controller->layout;
	        }else if(file_exists($pkgPath . Adroit::$controller . '.tpl')) {
	        	$layout = strtolower(Adroit::$package) . '/' . Adroit::$controller;
	        }else if(file_exists($pkgPath . 'base.tpl')) {
	        	$layout = strtolower(Adroit::$package) . '/base';
	        }else {
	        	$layout = 'base';
	        }
        }else {
	        if($controller->layout != null && file_exists($layoutPath . $controller->layout . '.tpl')) {
	            $layout = $controller->layout;
	        }else if(file_exists($layoutPath . Adroit::$controller . '.tpl')) {
	            $layout = Adroit::$controller;
	        }
        }
        return $layout;
    }
    
    public static function isXHR() {
        if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
        	return true;
        }else {
            return false;
        }
    }
}

if(!function_exists('__autoload')) {
    function __autoload($className) {
        $pkg = strtolower(Adroit::$package);
        if($className == 'BaseModel') {
            require_once(ADROIT_PATH . '/base/BaseModel.model.php');
        }else if($className == 'BaseView') {
        	require_once(ADROIT_PATH . '/base/Base.view.php');
        }else if($className == 'BaseController') {
        	require_once(ADROIT_PATH . '/base/Base.controller.php');
        }else if(substr($className, strlen($className)-4, 4) == 'View') {
            require_once(APP_PATH . 'view/' . ($pkg != '' ? $pkg .'/' : '') . substr($className, 0, strlen($className)-4) . '.view.php');
        }else if(substr($className, strlen($className)-10, 10) == 'Controller') {
            require_once(APP_PATH . 'controller/' . ($pkg != '' ? $pkg .'/' : '') . substr($className, 0, strlen($className)-10) . '.controller.php');
        }else if(substr($className, strlen($className)-6, 6) == 'Filter') {
            require_once(APP_PATH . 'filter/' . substr($className, 0, strlen($className)-6) . '.filter.php');
        }else {
            if(file_exists(ADROIT_PATH . '/util/' . $className . '.class.php')) {
                require_once(ADROIT_PATH . '/util/' . $className . '.class.php');
            }else if(file_exists(APP_PATH . 'lib/' . $className . '.class.php')) {
                require_once(APP_PATH . 'lib/' . $className . '.class.php');
		    }else if(file_exists(APP_PATH . 'model/' . $className . '.model.php')) {
	     	   require_once(APP_PATH . 'model/' . $className . '.model.php');
	    	}
		}
	}
}
		
ini_set('unserialize_callback_func', '__autoload');
?>